home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 09 - 1993 / 09.02 Feb 93 / Jörg's Folder / Development.4th < prev    next >
Encoding:
Text File  |  1992-11-10  |  31.9 KB  |  1,563 lines  |  [TEXT/NISI]

  1. ONLY MAC DEFINITIONS
  2. ALSO FORTH
  3. ALSO ASSEMBLER
  4.  
  5. GLOBAL VOCABULARY DEVELOPMENT
  6.  
  7. ONLY ASSEMBLER
  8. ALSO MAC
  9. ALSO DEVELOPMENT DEFINITIONS
  10. ALSO FORTH
  11.  
  12. GLOBAL CREATE MODULE.list     ( points to the last module record
  13.                               in the MODULE list. )
  14. MACH
  15. $41ED HERE 4- W!
  16. $-B86 HERE 2- W!
  17. \ VP @ HERE 2- W! 4 VP +!
  18. $2D084E75 ,
  19.  
  20. CODE ,IMMED    ( set bit 9 - the immediate bit - of the trap word )
  21.     JSR        HERE
  22.     MOVE.L    (A6)+,A0
  23.     ORI.W    #$0200,-2(A0)
  24.     RTS
  25. END-CODE IMMEDIATE
  26.  
  27. -2 ALLOT
  28.  
  29. : ,MARKS    ( set bit 9 - for diacSens = FALSE )
  30.     ; IMMEDIATE
  31.  
  32. -2 ALLOT
  33. : ,NEWOS    ( set bit 9, clear bit 10 - for OS GetTrapAddress calls )
  34.     ;
  35.     IMMEDIATE
  36.  
  37. -2 ALLOT
  38.  
  39. : ,CLEAR    ( set bit 9 of the trap word )
  40.     ; IMMEDIATE
  41.  
  42. CODE ,CASE        ( set bit 10 - the case-sensitive bit - for _CmpString )
  43.     JSR        HERE
  44.     MOVE.L    (A6)+,A0
  45.     ORI.W    #$0400,-2(A0)
  46.     RTS
  47. END-CODE IMMEDIATE
  48.  
  49. -2 ALLOT
  50.  
  51. : ,ASYNC    ( set bit 10 - the asynchronous bit - for device driver calls )
  52.     ; IMMEDIATE
  53.  
  54. -2 ALLOT
  55.  
  56. : ,SYS        ( set bit 10 to get a system heap operation )
  57.     ; IMMEDIATE
  58.  
  59. -2 ALLOT
  60.  
  61. : ,AUTO-POP        ( set bit 10 to have the trap return pop the top
  62.                   return address)
  63.     ; IMMEDIATE
  64.  
  65. CODE ,NEWTOOL    ( set bit 9 and 10 - for ToolBox GetTrapAddress calls )
  66.     JSR        HERE
  67.     MOVE.L    (A6)+,A0
  68.     ORI.W    #$0600,-2(A0)
  69.     RTS
  70. END-CODE IMMEDIATE
  71.  
  72. \ allocate the StripAddress mask
  73. GLOBAL CREATE StripAddress.mask MACH
  74. $41ED HERE 4- W!
  75. $-B6E HERE 2- W!
  76. $2D084E75 ,
  77.  
  78. \ allocate the SysEnvRec
  79. GLOBAL CREATE MACH2.SysEnvRec MACH
  80. $41ED HERE 4- W!
  81. $-B7E HERE 2- W!
  82. $2D084E75 ,
  83.  
  84. \ allocate the flags variable
  85. GLOBAL CREATE MACH2.flags MACH
  86. $41ED HERE 4- W!
  87. $-B82 HERE 2- W!
  88. $2D084E75 ,
  89.  
  90. \ bit 0 = Gestalt exists
  91. \ bit 1 = Apple Events exists
  92. \ bit 2 = SysEnvirons exists
  93. \ bit 3 = WaitNextEvent exists
  94. \ bit 4 = Used internally during System 7 COLD startup
  95.  
  96. ONLY ASSEMBLER
  97. ALSO MAC
  98. ALSO FORTH DEFINITIONS
  99.  
  100. \ create a variable for HERE
  101. GLOBAL CREATE (HERE) MACH
  102. $41ED HERE 4- W!
  103. $-1EC HERE 2- W!
  104. $2D084E75 ,
  105.  
  106. \ create a variable for High Level Event Handler chain
  107. GLOBAL CREATE HLE.handler MACH
  108. $41ED HERE 4- W!
  109. $-B8A HERE 2- W!
  110. $2D084E75 ,
  111.  
  112. 0    GLOBAL USER NEXT_TASK
  113. 4    GLOBAL USER S0
  114. 8    GLOBAL USER PS
  115. 12    GLOBAL USER RETURN_STK
  116. 40    GLOBAL USER HEAD
  117. 44    GLOBAL USER TAIL
  118. 48    GLOBAL USER CTR
  119. 52    GLOBAL USER PTR
  120. 56    GLOBAL USER ECHO
  121. 60    GLOBAL USER FILEID
  122. 62    GLOBAL USER V/WD.RefNum
  123. 64    GLOBAL USER CONTEXT
  124. 68    GLOBAL USER CURRENT
  125. 72    GLOBAL USER TaskWindowPointer
  126. 76    GLOBAL USER ABORT-ACTION
  127. 80    GLOBAL USER (ABORT)
  128. 84    GLOBAL USER (NUMBER)
  129. 88    GLOBAL USER (EXPECT)
  130. 92    GLOBAL USER (TYPE)
  131. 96    GLOBAL USER (?TERMINAL)
  132. 100    GLOBAL USER (QUERY)
  133. 104    GLOBAL USER PenLocation
  134. 108    GLOBAL USER TaskMenuBar
  135. 116    GLOBAL USER MenuData
  136. 124    GLOBAL USER ControlData
  137. 128    GLOBAL USER ControlHandle
  138. 136    GLOBAL USER DialogData
  139. 140    GLOBAL USER DialogHandle
  140. 144 GLOBAL USER UserVector
  141. 148    GLOBAL USER UserData
  142. 152    GLOBAL USER CONTENT-HOOK
  143. 156    GLOBAL USER DRAG-HOOK
  144. 160    GLOBAL USER GROW-HOOK
  145. 164    GLOBAL USER GOAWAY-HOOK
  146. 168    GLOBAL USER UPDATE-HOOK
  147. 172    GLOBAL USER ACTIVATE-HOOK
  148. 176    GLOBAL USER DEVICE_EXPECT
  149. 180    GLOBAL USER DEVICE_QTERM
  150. 184    GLOBAL USER DEVICE_TYPE
  151. 188    GLOBAL USER ATALK_SOCKET
  152. 190    GLOBAL USER DIALOG-HOOK
  153. 194    GLOBAL USER ZOOMIN-HOOK
  154. 198    GLOBAL USER ZOOMOUT-HOOK
  155. 202    GLOBAL USER C_Action
  156. 212    GLOBAL USER FileI/OID
  157.  
  158. ONLY MAC DEFINITIONS
  159. ALSO FORTH
  160. ALSO ASSEMBLER
  161.  
  162. GLOBAL
  163. CODE CmpString    ( str1 str2 - flag )    ( compares two strings )
  164.     MOVEQ.L    #0,D0
  165.     MOVE.L    4(A6),A0
  166.     MOVE.B    (A0)+,D0
  167.     SWAP.W    D0
  168.     MOVE.L    (A6),A1
  169.     MOVE.B    (A1)+,D0
  170.  
  171.     EXG.L    D4,A7
  172.             _CmpString
  173.     EXG.L    D4,A7
  174.     
  175.     ( returns a result code in D0, zero if they match )
  176.     
  177.     ADDQ.L    #4,A6
  178.     SUBQ.L    #1,D0    ( make result true if trap return is zero )
  179.     MOVE.L    D0,(A6)
  180.     RTS
  181. END-CODE
  182.  
  183. ONLY MAC
  184. ALSO ASSEMBLER
  185. ALSO DEVELOPMENT DEFINITIONS
  186. ALSO FORTH
  187.  
  188. HEADER str.#ifdef
  189.     DC.B    6
  190.     DC.B    '#ifdef'
  191. .ALIGN
  192.  
  193. HEADER str.#ifndef
  194.     DC.B    7
  195.     DC.B    '#ifndef'
  196. .ALIGN
  197.  
  198. HEADER str.#else
  199.     DC.B    5
  200.     DC.B    '#else'
  201. .ALIGN
  202.  
  203. HEADER str.#endif
  204.     DC.B    6
  205.     DC.B    '#endif'
  206. .ALIGN
  207.  
  208. : #endif ; IMMEDIATE
  209.  
  210. GLOBAL
  211. : exec.word ( name.string -- )
  212.     FIND DROP LINK>BODY EXECUTE
  213.     ;
  214.  
  215. : (#ifdef) 
  216.     ( lfa found.flag -- )
  217.     { | word.addr exit.flag }
  218.     IF
  219.         ( -- LFA )
  220.         DROP
  221.         ( get all the next words and bypass them until a #else, #ifdef,
  222.           #ifndef, #endif, open-paren, or back-slash is encountered, 
  223.           then execute it )
  224.         0 -> exit.flag
  225.         BEGIN
  226.             32 WORD ( -- a ) -> word.addr
  227.             word.addr C@
  228.             CASE
  229.                 1
  230.                 OF
  231.                     word.addr 1+ C@ DUP
  232.                     ASCII ( =
  233.                     SWAP ASCII \ =
  234.                     OR
  235.                     IF word.addr exec.word THEN
  236.                     
  237.                 ENDOF
  238.  
  239.                 5
  240.                 OF
  241.                     ( test to see if the word is a "#else" )
  242.                     word.addr 1+ C@ ASCII # 
  243.                     =
  244.                     IF
  245.                         ( perform the string comparison )
  246.                         word.addr ['] str.#else CmpString
  247.                         IF 
  248.                             1 -> exit.flag 
  249.                         THEN
  250.                     THEN
  251.                 ENDOF
  252.  
  253.                 6
  254.                 OF
  255.                     ( test to see if the word is a "#endif" or "#ifdef" )
  256.                     word.addr 1+ C@ ASCII #
  257.                     =
  258.                     IF
  259.                         ( attempt the string comparison )
  260.                         word.addr ['] str.#endif CmpString
  261.                         IF 1 -> exit.flag 
  262.                         ELSE
  263.                             word.addr ['] str.#ifdef CmpString
  264.                             IF 
  265.                                 1 -> exit.flag 
  266.                                 word.addr exec.word
  267.                             THEN
  268.                         THEN
  269.                     THEN
  270.                 ENDOF
  271.  
  272.                 7
  273.                 OF
  274.                     ( test to see if the word is a "#ifndef" )
  275.                     word.addr 1+ C@ ASCII #
  276.                     =
  277.                     IF
  278.                         ( attempt the string comparison )
  279.                         word.addr ['] str.#ifndef CmpString
  280.                         IF 
  281.                             1 -> exit.flag 
  282.                             word.addr exec.word
  283.                         THEN
  284.                     THEN
  285.                 ENDOF
  286.  
  287.             ENDCASE
  288.  
  289.             exit.flag
  290.         UNTIL
  291.     ELSE
  292.         DROP ( the address )
  293.         ( continue interpreting the words following the
  294.           #ifdef or #ifndef )
  295.     THEN
  296.     ;
  297.  
  298. : #ifdef
  299.     32 WORD FIND 0= ( -- lfa flag )
  300.     (#ifdef)
  301.     ;
  302.     IMMEDIATE
  303.  
  304. : #ifndef
  305.     32 WORD FIND 0= NOT ( -- lfa flag )
  306.     (#ifdef)
  307.     ;
  308.     IMMEDIATE
  309.  
  310. : #else
  311.     ( if this word gets executed it's because an #ifdef or #ifndef
  312.       was true, so the first part was compiled/executed.  If
  313.       #ifdef or #ifndef resolved to false, then this word
  314.       is bypassed and all the following words up to the #endif
  315.       are executed/compiled. )
  316.  
  317.     { | word.addr repeat.flag }
  318.     32 WORD -> word.addr
  319.  
  320.     word.addr  ['] str.#ifdef  CmpString
  321.     word.addr  ['] str.#ifndef CmpString
  322.     OR
  323.     IF
  324.         word.addr exec.word
  325.     ELSE
  326.         ( look for an #ifdef, #ifndef, #endif or comment char )
  327.         1 -> repeat.flag
  328.         BEGIN
  329.             word.addr 1+ C@ ASCII # =
  330.             IF 
  331.                 word.addr ['] str.#ifdef CmpString
  332.                 word.addr ['] str.#ifndef CmpString
  333.                 OR
  334.                 IF
  335.                     0 -> repeat.flag
  336.                     word.addr exec.word
  337.                 ELSE
  338.                     word.addr ['] str.#endif CmpString
  339.                     IF 0 -> repeat.flag THEN
  340.                 THEN
  341.             ELSE
  342.                 word.addr C@ 1 = 
  343.                 IF
  344.                     word.addr 1+ C@ DUP
  345.                     ASCII ( =
  346.                     SWAP ASCII \ =
  347.                     OR
  348.                     IF word.addr exec.word THEN
  349.                 THEN
  350.             THEN
  351.             repeat.flag
  352.         WHILE
  353.             32 WORD -> word.addr
  354.         REPEAT
  355.     THEN
  356.     ;
  357.     IMMEDIATE
  358.  
  359. : #define CREATE -4 ALLOT $4E75 W, ; IMMEDIATE
  360.  
  361. ( These next set of words set up the saving of the CURRENT and 
  362.   CONTEXT states.)
  363.  
  364. GLOBAL
  365. CODE push.VOCAB.state
  366.     MOVE.L    64(A4),-(A6)
  367.     MOVE.L    68(A4),-(A6)
  368.     RTS
  369. END-CODE MACH
  370.  
  371. GLOBAL
  372. CODE pop.VOCAB.state
  373.     ( context current -- )
  374.     MOVE.L    (A6)+,68(A4)
  375.     MOVE.L    (A6)+,64(A4)
  376. END-CODE MACH
  377.  
  378. #define _RECORDS_
  379.  
  380. $1F    CONSTANT count.mask    ( masks out the name flags in the dict. header )
  381. $40    CONSTANT MACH.bit    ( used for getting the MACH bit setting )
  382.  
  383. GLOBAL
  384. CODE LINK>SEG
  385.     MOVE.L    (A6),A0        \ get the Link field address
  386.     ADDQ.L    #4,A0        \ point to the name string
  387.     CLR.L    D0            \ clear out D0
  388.     MOVE.B    (A0),D0        \ get the length byte
  389.     ANDI.B    #$1F,D0        \ mask out the immed, mach, bits
  390.     ADDQ.L    #1,A0        \ point to the first byte of name
  391.     ADD.L    D0,A0        \ add the length
  392.     ADDQ.L    #1,A0        \ adjust for even address
  393.     MOVE.L    A0,D0        \ put in a data register
  394.     ANDI.B    #$FE,D0
  395.     MOVE.L    D0,(A6)        \ put sfa on stack
  396.     RTS
  397. END-CODE
  398.  
  399. GLOBAL
  400. CODE MCOMPILE    ( addr -- )
  401.     ( macro compile from an address up to an RTS )
  402.     HERE                \ get first free dictionary location
  403.     MOVE.L    (A6)+,A1    \ put it in A1
  404.     MOVE.L    (A6)+,A0    \ get the passed-in PFA
  405.     MOVE.W    #$4E75,D1    \ an RTS for comparison
  406.     CLR.L    D2            \ counter for ALLOT
  407.  
  408. @copycode
  409.     MOVE.W    (A0)+,D0
  410.     CMP.W    D1,D0
  411.     BEQ.S    @donecopy
  412.     
  413.     MOVE.W    D0,(A1)+
  414.     ADDQ.W    #2,D2
  415.     BRA.S    @copycode
  416.  
  417. @donecopy
  418.     MOVE.L    D2,-(A6)
  419.     ALLOT
  420.     RTS
  421. END-CODE
  422.  
  423. GLOBAL
  424. : is.MACH? 4 + C@ MACH.bit AND 0= NOT ;    ( lfa -- flag )
  425.  
  426. GLOBAL
  427. : is.name.field.word? link>seg W@ 1 = ; ( lfa -- flag )
  428.  
  429. : insert.offset     ( n -- )
  430.     HERE 4 - W@ L_EXT +
  431.     HERE 4 - W!
  432.     ;
  433.  
  434. GLOBAL
  435. : macro.compile
  436.     { lfa -- }
  437.     
  438.     ( first test for name-field words ( HEADER and local vars ) )
  439.     lfa link>seg DUP W@ 1 =
  440.     IF
  441.         ( -- sfa )
  442.         2+ DUP W@    ( get the first instruction )
  443.         CASE
  444.             $2D3C    ( MOVE.L    #addr,-(A6) )
  445.             OF
  446.                 ( -- cfa )
  447.                 DUP 2+ @            ( get the starting absolute address )
  448.                 HERE - 2-            ( get the PC offset from here to location )
  449.                 ( now test for CodeRec or *CodeRec )
  450.                 ( -- cfa offset )
  451.                 SWAP 8 + @ $12344321 =
  452.                 IF
  453.                     ( it is a *CodeRec )
  454.                     $207A W, W,        \ MOVEA.L d(PC),A0
  455.                     $41E8 W,        \ LEA d(A0),A0
  456.                     0     W,
  457.                     $2D08 W,        \ MOVE.L A0,-(A6)
  458.                 ELSE
  459.                     ( it is a CodeRec )
  460.                     $41FA W, W,        ( LEA         d(PC),A0 )
  461.                     $2D08 W,        ( MOVE.L    A0,-(A6) )
  462.                 THEN
  463.             ENDOF
  464.         
  465.             $4EAD    ( JSR d(A5) )
  466.             OF
  467.                 ( it is a local variable )
  468.                 ( -- cfa )
  469.                 4 + W@        ( get the A2 offset )
  470.                 $206A W, W,    ( MOVEA.L    d(A2),A0 )
  471.                 $41E8 W,    ( LEA        d(A0),A0 )
  472.                 0 W,
  473.                 $2D08 W,    ( MOVE.L    A0,-(A6) )
  474.             ENDOF
  475.         ENDCASE
  476.     ELSE
  477.         ( it is some sort of normal variable )
  478.         DROP    ( the sfa )
  479.         ( first do a special handler for PC-relative macro variables )
  480.         lfa is.MACH?
  481.         lfa LINK>BODY W@ DUP
  482.         $41FA =                    ( is the first instruction an LEA d(PC),A0 )
  483.         SWAP  $207A = OR AND    ( is the first instruction an MOVEA d(PC),A0 )
  484.         IF
  485.             HERE                        ( save the current HERE value )
  486.             lfa LINK>BODY 2+ DUP W@ +    ( save the absolute address )
  487.             lfa LINK>BODY mcompile
  488.             ( -- old.here addr )
  489.             SWAP 2+ DUP                 ( -- addr @ext.word @ext.word )
  490.             ROT SWAP - SWAP W!
  491.         ELSE
  492.             ( do a normal macro compile )
  493.             lfa LINK>BODY mcompile
  494.         THEN
  495.     THEN
  496.     ;
  497.  
  498. : extract.offset    ( -- n )
  499.  
  500.     HERE 4 - @ $FF00FFFF AND $70002D00 =
  501.     ( is it equal to MOVEQ.L n,D0;  MOVE.L D0,-(A6) )
  502.     IF
  503.         HERE 8 - W@ $2D3C = NOT
  504.         IF
  505.             ( the constant is not ambiguous )
  506.             HERE 4 - W@ $00FF AND
  507.             -4 ALLOT
  508.         ELSE
  509.             CR ." Can't distinguish compiled constant at " HERE 6 - .
  510.             CR ." Both MOVE.L and MOVEQ.L operands!"
  511.             ABORT
  512.         THEN
  513.     ELSE
  514.         ( then check for MOVE.L #n,D0;  MOVE.L D0,-(a6) )
  515.         HERE 8 - W@ $203C =
  516.         HERE 2-  W@ $2D00 = AND
  517.         IF
  518.             HERE 6 - @
  519.             -8 ALLOT
  520.         ELSE
  521.             ( check for MOVE.L #n,-(A6) )
  522.             HERE 6 - W@ $2D3C =
  523.             IF
  524.                 HERE 4 - @
  525.                 -6 ALLOT
  526.             ELSE
  527.                 CR 7 EMIT ." Could not find compiled constant offset."
  528.                 ABORT
  529.             THEN
  530.         THEN
  531.     THEN
  532.     ;
  533.  
  534. GLOBAL
  535. : .OF.
  536.     ( this word attempts to create a record offset address, either on
  537.       the stack, or by compiling the code for one.)
  538.  
  539.     { | >IN.count -- }
  540.  
  541.     >IN @ -> >IN.count    ( save it in case we have to back up )
  542.  
  543.     32 WORD             ( -- word.addr )
  544.     DUP C@ 0=
  545.     IF
  546.         ( - addr )
  547.         DROP CR
  548.         ." A record word must follow .OF."
  549.         ABORT
  550.  
  551.     ELSE
  552.         FIND                ( addr -- lfa flag )
  553.         0= ABORT" The word following .OF. could not be found."
  554.         ( -- lfa )
  555.  
  556.         STATE @ 0=
  557.         IF
  558.             ( we are not in a compiling state )
  559.             DEPTH ?DUP 0= ABORT" .OF. needs an offset constant on the stack!"
  560.  
  561.             LINK>BODY EXECUTE    ( -- n depth [addr] )
  562.             DEPTH ?DUP 0= ABORT" .OF. needs an address and offset on the stack."
  563.  
  564.             ( -- n depth addr depth )
  565.             ROT - 1 = NOT ABORT" The word following .OF. must push an address on the stack."
  566.  
  567.             +
  568.         ELSE
  569.             ( -- lfa )
  570.             ( we are compiling, so compiling the following word should
  571.               compile the code for that word into the dictionary.)
  572.             DUP
  573.             ['] ['] BODY>LINK =            ( -- lfa flag )
  574.             1 PICK ['] ^ BODY>LINK =    ( -- lfa flag flag )
  575.             OR
  576.             IF
  577.                 ( -- lfa )
  578.                 extract.offset SWAP
  579.                 ( -- n lfa )
  580.                 LINK>BODY EXECUTE
  581.                 insert.offset
  582.  
  583.             ELSE
  584.                 ( -- lfa )
  585.  
  586.                 ( the word is hopefully some sort of variable 
  587.                   and has to be compiled. )
  588.  
  589.                 extract.offset SWAP
  590.                 DUP is.MACH?
  591.                 IF
  592.                     ( -- n lfa )
  593.                     macro.compile ( n lfa -- n )
  594.                     ( now install the final offset )
  595.                     insert.offset
  596.                 ELSE
  597.                     ( -- n lfa )
  598.                     DUP is.name.field.word?
  599.                     IF
  600.                         ( -- n lfa )
  601.                         macro.compile
  602.                         insert.offset
  603.                     ELSE
  604.                         DROP
  605.                         ( since we are compiling a JSR, just compile the 
  606.                           offset number, then compile the JSR )
  607.                         [COMPILE] LITERAL
  608.                         >IN.count >IN !
  609.                         [COMPILE] [COMPILE]
  610.                     THEN
  611.                 THEN
  612.             THEN
  613.  
  614.             ( now check for a following fetch or store, and if so,
  615.               modify the MOVE.L A0,-(A6) to a MOVE.L (A0),-(A6) )
  616.  
  617.             HERE 2- W@ $2D08 =
  618.             IF
  619.                 >IN @ -> >IN.count
  620.                 32 WORD FIND    ( -- lfa flag )
  621.                 0=
  622.                 IF
  623.                     ( could not find the word, back out )
  624.                     DROP >IN.count >IN !
  625.                 ELSE
  626.                     ( -- lfa )
  627.                     CASE
  628.                         ['] @ BODY>LINK
  629.                         OF
  630.                             $2D10 HERE 2- W!
  631.                         ENDOF
  632.                                 
  633.                         ['] W@ BODY>LINK
  634.                         OF
  635.                             $4280 HERE 2- W!    \ CLR.L  D0
  636.                             $3010 W,            \ MOVE.W (A0),D0
  637.                             $2D00 W,            \ MOVE.L D0,-(A6)
  638.                         ENDOF
  639.         
  640.                         ['] C@ BODY>LINK
  641.                         OF
  642.                             $4280 HERE 2- W!    \ CLR.L    D0
  643.                             $1010 W,            \ MOVE.B (A0),D0
  644.                             $2D00 W,            \ MOVE.L D0,-(A6)
  645.                         ENDOF
  646.  
  647.                         ['] ! BODY>LINK
  648.                         OF
  649.                             $209E HERE 2- W!    \ MOVE.L (A6)+,(A0)
  650.                         ENDOF
  651.  
  652.                         ['] W! BODY>LINK
  653.                         OF
  654.                             $30AE HERE 2- W!    \ MOVE.W 2(A6),(A0)
  655.                             2 W,
  656.                             $588E W,            \ ADDQ.L #4,A6
  657.                         ENDOF
  658.  
  659.                         ['] C! BODY>LINK
  660.                         OF
  661.                             $10AE HERE 2- W!    \ MOVE.B 3(A6),(A0)
  662.                             3 W,
  663.                             $588E W,            \ ADDQ.L #4,A6
  664.                         ENDOF
  665.                                 
  666.                         ( the next word is not a fetch, back out )
  667.                         >IN.count >IN !
  668.                     ENDCASE
  669.                 THEN
  670.             THEN
  671.         THEN
  672.     THEN
  673.     ;
  674.     IMMEDIATE
  675.  
  676. GLOBAL
  677. : is.white.space?
  678.     C@ DUP $20 = SWAP $09 = OR ;
  679.  
  680. GLOBAL
  681. : GET.NEXT.WORD
  682.     { | start.addr addr word.addr -- addr }
  683.     ( imitate WORD but remove white space )
  684.     
  685.     WORD -> word.addr 
  686.     word.addr 1+ -> addr
  687.     BEGIN
  688.         addr is.white.space?
  689.     WHILE
  690.         1 +> addr
  691.     REPEAT
  692.     
  693.     addr -> start.addr
  694.     1 +> addr
  695.     
  696.     BEGIN
  697.         addr is.white.space? NOT
  698.     WHILE
  699.         1 +> addr
  700.     REPEAT
  701.     
  702.     addr start.addr - word.addr C!
  703.     start.addr word.addr 1+ = NOT
  704.     IF
  705.         ( move the string )
  706.         start.addr word.addr 1+ word.addr C@
  707.         CMOVE
  708.     THEN
  709.     word.addr
  710.     ;
  711.  
  712. -2 ALLOT
  713.  
  714. : ;RECORD     ( this word is used to end the record definitions  )
  715.     ;
  716.  
  717. GLOBAL
  718. : SizeOf(        ( word to return the size of a defined record )
  719.     ASCII ) get.next.word FIND
  720.     0=
  721.     IF
  722.         CR
  723.         ." Could not find the record definition " 
  724.         COUNT TYPE CR ABORT
  725.     ELSE
  726.         ( -- lfa )
  727.         LINK>BODY 4+ @    ( get the size stored at offset 4 )
  728.     THEN
  729.     ;
  730.  
  731. : RECORD.OFFSET
  732.     ( offset - new.offset )
  733.     
  734.     ( This word is the defining word for record constants
  735.       created by :RECORD.  This word is not typically used
  736.       directly.)
  737.  
  738.     DUP CONSTANT
  739.     
  740.     32 WORD ( -- offset @string )
  741.     DUP C@ 0= ABORT" A constant or constant definition must follow a record item."
  742.     FIND    ( -- offset addr flag )
  743.     0= 
  744.     IF
  745.         ( -- offset addr )
  746.         DUP NUMBER?         ( -- offset addr n f )
  747.         0= ABORT" Could not find type word or size constant for record definition constant."
  748.         SWAP DROP
  749.  
  750.     ELSE    
  751.         ( -- offset addr )
  752.         DEPTH SWAP
  753.         LINK>BODY EXECUTE
  754.         ( -- offset depth [n] )
  755.         DEPTH ROT - 1 = NOT ABORT" The record item type must resolve to a constant."
  756.     THEN
  757.     ( -- offset n )
  758.     +
  759.     ;
  760.  
  761. : VarRec ;
  762. : *VarRec ;
  763. : CodeRec ;
  764. : *CodeRec ;
  765.  
  766. GLOBAL
  767. : allocate.record
  768.     ( The defining word for a record variable.  When a record 
  769.       is defined, as in: "… RName rec.var1 type …", this word
  770.       is executed by the Record Definition word RName. )
  771.       
  772.     MOVE.L (A7)+,-(A6)    ( get the pfa for the record size )
  773.     ( -- pfa )
  774.     @                    ( -- size )
  775.     >IN @                ( -- size >IN.count )
  776.     32 WORD DROP        ( skip over the record variable name )
  777.     32 WORD FIND        ( -- size >IN.count addr flag )
  778.     ROT >IN !
  779.     0= NOT
  780.     IF
  781.         ( -- size lfa )
  782.         LINK>BODY
  783.         CASE
  784.             
  785.             ['] VarRec ( allocate a variable record )
  786.             OF
  787.                 ( -- size )
  788.                 VARIABLE
  789.                 4 - VALLOT
  790.             ENDOF
  791.             
  792.             ['] *VarRec ( allocate a VARIABLE space record pointer )
  793.             OF
  794.                 DROP HERE
  795.                 ( -- here )
  796.                 VARIABLE
  797.                 $2050 SWAP 4 + W!    \ MOVEA.L    (A0),A0                
  798.                 $41E8 W,            \ LEA        d(A0),A0
  799.                 0 W,
  800.                 $2D08 W,            \ MOVE.L    A0,-(A6)
  801.                 $4E75 W,
  802.                 
  803.             ENDOF
  804.                 
  805.             ['] CodeRec ( allocate a code record )
  806.             OF
  807.                 ( -- size )
  808.                 ( use CREATE to create a name field word, then 
  809.                   modify it )
  810.                 ( -- size )
  811.                 CREATE -4 ALLOT HERE
  812.                 ( -- size here )
  813.                 1         NP @ 4 - W!    \ set the segment field for a Name field word
  814.                 $2D3C     NP @ 2- W!    \ MOVE.L #here,-(A6)
  815.                         NP @ !        \ store HERE
  816.                 $4E75 NP @ 4 + W!    \ RTS
  817.                 $1234 NP @ 6 + W!    \ make this exactly like a HEADER definition
  818.                 8 NP +!                \ allocate the name space
  819.                 ALLOT
  820.             ENDOF
  821.                 
  822.             ['] *CodeRec ( allocate a code space record pointer )
  823.             OF
  824.                 ( -- size )
  825.                 ( use CREATE to create a name field word, then 
  826.                   modify it )
  827.                 DROP
  828.                 CREATE HERE 4 -
  829.                 ( - addr )
  830.                 1         NP @ 4 - W!    \ make it a name space word
  831.                 $2D3C     NP @ 2- W!    \ MOVE.L #here,-(A6)
  832.                         NP @ !        \ store the starting address
  833.                 $4E75 NP @ 4 + W!    \ RTS
  834.                 $1234 NP @ 6 + W!    \ add constant to make it like a standard HEADER
  835.                 $4321 NP @ 8 + W!    \ add a constant for an indirect record pointer
  836.                 10 NP +!            \ allocate the name space
  837.             ENDOF
  838.         ENDCASE
  839.         32 WORD DROP    \ skip over the type word cuz we already decoded it
  840.     ELSE
  841.         CR
  842.         ." A type definition must follow a typed variable allocation." CR ABORT
  843.     THEN
  844.     ;
  845.  
  846. GLOBAL
  847. : :RECORD    ( this word starts the record definitions process )
  848.  
  849.     STATE @ 0= NOT
  850.     IF
  851.         CR ." :RECORD can only be used outside of a colon definition."
  852.         ABORT
  853.     ELSE
  854.  
  855.     CREATE -4 ALLOT            ( overwrite the default code the CREATE puts in )
  856.     COMPILE allocate.record    ( set the defining word for the record )
  857.     HERE            ( get the address for the record size )
  858.     4 ALLOT            ( allocate space for the record size )        
  859.     ( -- addr )
  860.     0            ( starting record offset )
  861.     BEGIN
  862.         >IN @                    ( save the current spot in the TIB )
  863.         32 WORD DUP              ( -- addr offset count addr addr )
  864.         FIND                    ( is the string a valid definition? )
  865.                                 ( There are only three valid words - 
  866.                                   the two comment words and ;RECORD )
  867.         ( -- addr offset count addr lfa flag )
  868.         IF
  869.             1 PICK C@ 1 =
  870.             IF
  871.                 ( -- addr offset count addr lfa )
  872.                 ( if it is a comment string, execute the operator )
  873.                 1 PICK 1+ C@ DUP ASCII (    =
  874.                 SWAP ASCII \                 =
  875.                 OR
  876.                 IF
  877.                     LINK>BODY EXECUTE
  878.                     DROP DROP 
  879.                     0
  880.                 ELSE
  881.                     CR
  882.                     1 PICK COUNT TYPE 
  883.                     ."  is bad record definition syntax." CR ABORT
  884.                 THEN
  885.             ELSE
  886.                 ( -- addr offset count addr lfa )
  887.                 LINK>BODY
  888.                 ['] ;RECORD  =
  889.                 IF
  890.                     DROP DROP 1
  891.                 ELSE
  892.                     CR
  893.                     ." Must end record definition with ;RECORD." CR ABORT
  894.                 THEN
  895.             THEN
  896.         ELSE
  897.             ( -- addr offset count addr lfa )
  898.             DROP DROP
  899.             >IN !
  900.             RECORD.OFFSET
  901.             0
  902.         THEN
  903.     UNTIL
  904.     ( -- addr offset )
  905.     SWAP !
  906.     THEN
  907.     ;
  908.  
  909. ' insert.offset        BODY>LINK 4+ DUP C@ $20 OR SWAP C!
  910. ' extract.offset    BODY>LINK 4+ DUP C@ $20 OR SWAP C!
  911. ' RECORD.OFFSET        BODY>LINK 4+ DUP C@ $20 OR SWAP C!
  912. ' allocate.record    BODY>LINK 4+ DUP C@ $20 OR SWAP C!
  913.  
  914. ONLY ASSEMBLER
  915. ALSO DEVELOPMENT
  916. ALSO FORTH
  917. ALSO MAC DEFINITIONS
  918.  
  919. ( === Compiler support words. === )
  920.  
  921.     ( The Little Guy:John's Stuff )
  922.     ( IRIDIUM.SYS:IRIDIUM:SYSTEMS:SYS_TEAM:Network Ops Plan )
  923.  
  924.     #ifndef _MacTypes_
  925.         INCLUDE" IRIDIUM.SYS:IRIDIUM:SYSTEMS:SYS_TEAM:Network Ops Plan:Includes:MacTypes.4th.inc"
  926.     #endif
  927.  
  928.     INCLUDE" IRIDIUM.SYS:IRIDIUM:SYSTEMS:SYS_TEAM:Network Ops Plan:Includes:Modules.4th"
  929.  
  930.     #ifndef _FSEQU_
  931.         INCLUDE" IRIDIUM.SYS:IRIDIUM:SYSTEMS:SYS_TEAM:Network Ops Plan:Includes:FSEqu.Txt"
  932.     #endif 
  933.  
  934.     #ifndef _SYSEQU_
  935.         INCLUDE" IRIDIUM.SYS:IRIDIUM:SYSTEMS:SYS_TEAM:Network Ops Plan:Includes:SysEqu.Txt"
  936.     #endif 
  937.  
  938. push.VOCAB.state
  939. ONLY DEVELOPMENT
  940. ALSO FORTH
  941. ALSO ASSEMBLER
  942. ALSO MAC DEFINITIONS
  943.  
  944. DECIMAL
  945.  
  946. 1536 Insert.MODULE _SYSENV_
  947.  
  948. $9F        CONSTANT UnknownTrap.#
  949. $9F        CONSTANT Unimplemented.#
  950. $90        CONSTANT SysEnvirons.#
  951. $1AD    CONSTANT Gestalt.#
  952.  
  953. $A89F    CONSTANT UnknownTrap.opcode
  954. $A89F    CONSTANT Unimplemented.opcode
  955. $A090    CONSTANT SysEnvirons.opcode
  956. $A1AD    CONSTANT Gestalt.opcode
  957.  
  958. ( ===== System Globals ===== )
  959.  
  960. $12F    CONSTANT CPUFlag ( byte )
  961. $21E    CONSTANT KbdType ( byte )
  962. $A58    CONSTANT SysMap        ( global that contains System Map reference # )
  963. $B22    CONSTANT HWCfgFlags
  964. $B22    CONSTANT SCSIFlags
  965.  
  966. ( ===== System Global Constants ===== )
  967.  
  968. 15        CONSTANT SCSI.port.present.bit
  969. $8000    CONSTANT SCSI.port.present.mask
  970. 14        CONSTANT New.Clock.Chip.Present.bit
  971. $4000    CONSTANT New.Clock.Chip.Present.mask
  972. 13        CONSTANT Extra.PRAM.Valid.bit
  973. $2000    CONSTANT Extra.PRAM.Valid.mask ( at boottime )
  974. 4        CONSTANT has.FPU.bit ( in HwCfgFlags )
  975. $0010    CONSTANT has.FPU.mask
  976.  
  977. 0    CONSTANT OSTrap
  978. 1    CONSTANT ToolTrap
  979.  
  980. ( SysEnvirons returned keyboard constants )
  981. 0    CONSTANT envUnknownKbd        ( Macintosh Plus keyboard with keypad )
  982. 1    CONSTANT envMacKbd            ( Macintosh keyboard )
  983. 2    CONSTANT envMacAndPad        ( Macintosh keyboard and keypad )
  984. 3    CONSTANT envMacPlusKbd        ( Macintosh Plus keyboard )
  985. 4    CONSTANT envAExtendKbd        ( Apple extended Kbd )
  986. 5    CONSTANT envStandADBKbd        ( standard Apple Desktop Bus keyboard )
  987. 6    CONSTANT envPortADBKbd        ( Portable Keyboard )
  988. 7    CONSTANT envPortISOADBKbd    ( Portable Keyboard (ISO) )
  989. 8    CONSTANT envStdISOADBKbd    ( Apple Standard Keyboard (ISO) )
  990. 9    CONSTANT envExtISOADBKbd    ( Apple Extended Keyboard (ISO) )
  991. 10    CONSTANT envADBKbdII        ( Apple Keyboard II )
  992. 11    CONSTANT envADBISOKbdII        ( Apple Keyboard II (ISO) )
  993.  
  994. 11    CONSTANT no.of.kbds
  995.  
  996. _SYSENV_ restore.name.space
  997.  
  998. ( ===== SysEnviron record constants ===== )
  999.  
  1000. :RECORD SysEnvRec
  1001.     environsVersion    short
  1002.     machineType        short
  1003.     systemVersion    short
  1004.     processor        short
  1005.     hasFPU            char
  1006.     hasColorQD        char
  1007.     keyBoardType    short
  1008.     atDrvrVersNum    short
  1009.     sysVRefNum        short
  1010. ;RECORD
  1011.  
  1012. CODE NGetTrapAddress.Tool
  1013.     ( trap# -- addr )
  1014.     MOVE.W    2(A6),D0
  1015.     EXG.L    D4,A7
  1016.             _GetTrapAddress ,NEWTOOL
  1017.     EXG.L    D4,A7
  1018.     MOVE.L    A0,(A6)
  1019.     RTS
  1020. END-CODE MACH
  1021.  
  1022. CODE NGetTrapAddress.OS
  1023.     ( trap# -- addr )
  1024.     MOVE.W    2(A6),D0
  1025.     EXG.L    D4,A7
  1026.             _GetTrapAddress ,IMMED ( same as ,NEWOS )
  1027.     EXG.L    D4,A7
  1028.     MOVE.L    A0,(A6)
  1029.     RTS
  1030. END-CODE MACH
  1031.  
  1032. : NumToolboxTraps ( -- number )
  1033.     $6E NGetTrapAddress.Tool    ( _InitGraf )
  1034.     $AA6E NGetTrapAddress.Tool
  1035.     =
  1036.     IF $200 ELSE $400 THEN
  1037.     ;
  1038.  
  1039. GLOBAL
  1040. : GetTrapType        ( trap -- traptype )
  1041.     $0800 
  1042.     AND
  1043.     0>
  1044.     IF ToolTrap ELSE OSTrap THEN    
  1045.     ;
  1046.  
  1047. GLOBAL
  1048. : TrapAvailable?  { trap.# | trapType -- flag }
  1049.  
  1050.     trap.# GetTrapType -> trapType
  1051.     trapType ToolTrap = 
  1052.     IF
  1053.         trap.#
  1054.         $07FF AND
  1055.         -> trap.#
  1056.         trap.# NumToolboxTraps
  1057.         < NOT
  1058.         IF
  1059.             UnknownTrap.# -> trap.#
  1060.         THEN
  1061.     THEN
  1062.     trap.#
  1063.     trapType ToolTrap =
  1064.     IF
  1065.         NGetTrapAddress.Tool
  1066.     ELSE
  1067.         NGetTrapAddress.OS
  1068.     THEN
  1069.     UnknownTrap.# NGetTrapAddress.Tool
  1070.     = NOT
  1071.     ;
  1072.  
  1073. GLOBAL
  1074. : Gestalt.Exist?
  1075.     ( -- flag )
  1076.     Gestalt.opcode TrapAvailable?
  1077.     ;
  1078.  
  1079. GLOBAL
  1080. : SysEnvirons.Exist?
  1081.     ( -- flag )
  1082.     SysEnvirons.opcode TrapAvailable?
  1083.     ;
  1084.  
  1085. ( here is included code to execute when SysEnvirons is not available )
  1086.  
  1087. : setmachineType
  1088.     ( -- n )
  1089.  
  1090.     ROMBase @ 9 + C@ $FF
  1091.     = NOT
  1092.     IF
  1093.         ( it is not a MAC XL )
  1094.         ROM85 W@ $8000 AND
  1095.         0=
  1096.         IF
  1097.             ( it is a 512KE or better -
  1098.               if it has the new clock chip it is a Mac Plus )
  1099.             HWCfgFlags W@ 
  1100.             New.Clock.Chip.Present.mask AND
  1101.             0=
  1102.             IF
  1103.                 ( new clock chip is not present - a 512KE )
  1104.                 1
  1105.             ELSE
  1106.                 ( at least a Plus )
  1107.                 ( test for Mac SE or Mac II )
  1108.                 ROMBase @ 8 + W@
  1109.                 CASE
  1110.                     $75 OF 2 ENDOF ( a MAC Plus )
  1111.                     $76 OF 3 ENDOF ( a MAC SE )
  1112.                     $78 OF 4 ENDOF ( a Mac II )
  1113.                     ( else it is an unknown Mac )
  1114.                     0 SWAP
  1115.                 ENDCASE
  1116.             THEN
  1117.         ELSE
  1118.             ( it's a 128 or 512K Mac)
  1119.             -1 
  1120.         THEN
  1121.     ELSE
  1122.         ( it is a Lisa )
  1123.         -2
  1124.     THEN
  1125.     ;
  1126.  
  1127. : set.processor.type
  1128.     (  -- n )
  1129.     CPUFlag C@ 3 >
  1130.     IF
  1131.         0
  1132.     ELSE
  1133.         CPUFlag C@ 1+
  1134.     THEN
  1135.     ;
  1136.  
  1137. : set.FPU.exist
  1138.     ( -- n )
  1139.     HWCfgFlags W@ has.FPU.mask AND
  1140.     0=
  1141.     IF
  1142.         0
  1143.     ELSE
  1144.         1
  1145.     THEN
  1146.     ;
  1147.  
  1148. CODE set.Color.QD.exist
  1149.     ( -- n )
  1150.     MOVE.W    ROM85,-(A6)
  1151.     CMPI.W    #$3FFF,(A6)
  1152.     BHI.S    @noCQD
  1153.  
  1154.     MOVE.W    #1,(A6)
  1155.     BRA.S    @addpad
  1156.  
  1157. @noCQD
  1158.     CLR.W    (A6)
  1159. @addpad
  1160.     CLR.W    -(A6)
  1161.     RTS
  1162. END-CODE
  1163.  
  1164. ( Comparing keyboard type in KbdType, and the value returned by SysEnvirons
  1165.  
  1166. KbdType     $03 $13 $0B $02 $01 $06 $07 $04 $05 $08 $09
  1167.              |   |   |   |   |   |   |   |   |   |   |
  1168. SysEnvirons $01 $02 $03 $04 $05 $06 $07 $08 $09 $0A $0B
  1169.              |   |   |   |   |   |   |   |   |   |   |
  1170.              |   |   |   |   |   |   |   |   |   |   Apple Keyboard II (ISO)
  1171.              |   |   |   |   |   |   |   |   |   Apple Keyboard II
  1172.              |   |   |   |   |   |   |   |   Apple Extended Keyboard (ISO)
  1173.              |   |   |   |   |   |   |   Apple Standard Keyboard (ISO)
  1174.              |   |   |   |   |   |   Portable Keyboard (ISO)
  1175.              |   |   |   |   |   Portable Keyboard
  1176.              |   |   |   |   standard Apple Desktop Bus keyboard
  1177.              |   |   |   Apple extended Kbd
  1178.              |   |   Macintosh Plus keyboard
  1179.              |   Macintosh keyboard and keypad
  1180.              Macintosh keyboard
  1181. )
  1182.  
  1183. CODE get.keyboard.type
  1184.     ( -- type )
  1185.     BRA.S    @dokb
  1186.  
  1187.     ( Compile a CONSTANT array of keyboard types )
  1188.     DC.B    $00
  1189.     DC.B    $03 
  1190.     DC.B    $13 
  1191.     DC.B    $0B
  1192.     DC.B    $02 
  1193.     DC.B    $01 
  1194.     DC.B    $06 
  1195.     DC.B    $07 
  1196.     DC.B    $04 
  1197.     DC.B    $05 
  1198.     DC.B    $08
  1199.     DC.B    $09
  1200.  
  1201. @dokb
  1202.     LEA        -2(PC),A0
  1203.     MOVE.B    KbdType,D0                \ get current keyboard type
  1204.     MOVE.W    #no.of.kbds,D1
  1205.     SUBQ.W    #1,D1
  1206. @next.type
  1207.     CMP.B    -(A0),D0
  1208.     DBEQ    D1,@next.type
  1209.  
  1210.     ADDQ.W    #1,D1
  1211.     EXT.L    D1
  1212.     MOVE.L    D1,-(A6)
  1213.     RTS
  1214. END-CODE
  1215.  
  1216. ( Now we need to get the AppleTalk version number )
  1217.  
  1218. : get.AppleTalk.Version
  1219.     ( -- version )
  1220.  
  1221.     ( first check SPConfig and PortBUse )
  1222.     SPConfig C@ $0F AND
  1223.     1 =
  1224.  
  1225.     ( port is configured for ATalk, check for PortBUse )
  1226.     $291 ( PortBUse ) C@ 0>
  1227.     AND
  1228.  
  1229.     $291 ( PortBUse ) C@ $0F AND
  1230.     1 = 
  1231.     AND
  1232.     IF
  1233.         ( AppleTalk .MPP is open, so get the version number )
  1234.         UTableBase @ 36 + @    ( addr of .MPP DCE )
  1235.         7 + C@
  1236.     ELSE
  1237.         ( AppleTalk not open )
  1238.         0
  1239.     THEN
  1240.     ;
  1241.  
  1242. GLOBAL
  1243. : HGetVInfo
  1244.     ( This routine used the variable array "file.iopb" and "vol.name"
  1245.       and calls the ROM routine HGetVInfo, using a passed-in volume ID.)
  1246.  
  1247.     { volume.ID @file.ioPB @vol.name -- resultcode }
  1248.  
  1249.     0 ioCompletion            .OF. @file.ioPB !
  1250.     @vol.name ioFileName    .OF. @file.ioPB !
  1251.     volume.ID ioVRefNum        .OF. @file.iopb W!
  1252.     0 ioVolIndex            .OF. @file.ioPB W!
  1253.     @file.iopb CALL HGetVInfo ( -- result )
  1254.     ;
  1255.  
  1256. GLOBAL
  1257. : get.THE.blessed.WD
  1258.     ( This routine gets the Working directory number of the
  1259.       blessed folder that contains the current open system file -
  1260.       use this routine when SysEnvirons is not available.)
  1261.  
  1262.     ( -- WDRefNum )
  1263.  
  1264.     { | [ 118 LALLOT ] @file.ioPB -- }
  1265.  
  1266.     ( do it the hard and scary way )
  1267.  
  1268.     0            ioCompletion    .OF. ^ @file.iopb !
  1269.     0            ioVRefNum        .OF. ^ @file.iopb W!
  1270.     SysMap W@    ioRefNum        .OF. ^ @file.iopb W!
  1271.     0            ioFCBIndex        .OF. ^ @file.iopb !
  1272.     ^ @file.iopb CALL GetFCBInfo ( -- result.code )
  1273.     0=
  1274.     IF
  1275.         ioVRefNum .OF. ^ @file.iopb W@
  1276.         DUP 0=
  1277.         IF
  1278.             ( dir.ID -- )
  1279.             ( either the volume is MFS or there is no blessed
  1280.               folder on this volume )
  1281.  
  1282.             ioVSigWord .OF. ^ @file.iopb W@
  1283.             TSigWord =
  1284.             IF
  1285.                 ( it's an HFS volume with no blessed folder, so it's
  1286.                   not the boot volume.  Use the global BootDrive to
  1287.                   find the boot drive and get it's blessed folder ID.)
  1288.                 DROP
  1289.                 BootDrive W@
  1290.                 ^ @file.ioPB
  1291.                 0
  1292.                 ( -- vol.ID @file.ioPB @vol.name )
  1293.                 HGetVInfo
  1294.                 0=
  1295.                 IF
  1296.                     ioVFndrInfo .OF. ^ @file.iopb @ 
  1297.                 ELSE
  1298.                     ( a fatal error occurred )
  1299.                     0
  1300.                 THEN
  1301.             THEN
  1302.         THEN
  1303.         ( -- dir.ID )
  1304.     ELSE
  1305.         ( a fatal error occurred )
  1306.         0
  1307.     THEN
  1308.     ( -- WDRefNum )
  1309.     ;
  1310.  
  1311. CODE fake.SysEnv
  1312.     ( SysEnvRec version -- SysEnvRec result )
  1313.  
  1314.     MOVE.L    A3,-(A7)    \ save A3
  1315.  
  1316.     MOVE.L    4(A6),A3    \ get the SysEnvRec pointer
  1317.  
  1318.     MOVEQ.L    #1,D0        \ set the Version number
  1319.     MOVE.W    D0,(A3)+
  1320.  
  1321.     setmachineType        \ get the Machine type
  1322.     MOVE.L    (A6)+,D0
  1323.     MOVE.W    D0,(A3)+
  1324.  
  1325.     MOVEQ.L    #0,D0        \ set the system file version
  1326.     MOVE.W    D0,(A3)+
  1327.  
  1328.     set.processor.type    \ get the CPU type
  1329.     MOVE.L    (A6)+,D0
  1330.     MOVE.W    D0,(A3)+
  1331.  
  1332.     set.FPU.exist        \ is there a floating point processor
  1333.     MOVE.L    (A6)+,D0
  1334.     MOVE.B    D0,(A3)+
  1335.  
  1336.     set.Color.QD.exist    \ is color QuickDraw available
  1337.     MOVE.L    (A6)+,D0
  1338.     MOVE.B    D0,(A3)+
  1339.  
  1340.     get.keyboard.type    \ which keyboard are we using
  1341.     MOVE.L    (A6)+,D0
  1342.     MOVE.W    D0,(A3)+
  1343.  
  1344.     get.AppleTalk.Version
  1345.     MOVE.L    (A6)+,D0
  1346.     MOVE.W    D0,(A3)+
  1347.  
  1348.     get.THE.blessed.WD
  1349.     MOVE.L    (A6)+,D0
  1350.     MOVE.W    D0,(A3)+
  1351.  
  1352.     MOVE.L    (A7)+,A3
  1353.     MOVE.L    #-5500,(A6)
  1354.     RTS
  1355. END-CODE
  1356.  
  1357. GLOBAL
  1358. CODE SysEnvirons
  1359.     ( SysEnvRec version -- SysEnvRec result )
  1360.     SysEnvirons.Exist?
  1361.     TST.L    (A6)+
  1362.     BEQ.S    @noSysEnv
  1363.  
  1364.     EXG        D4,A7
  1365.     MOVE.W    2(A6),D0
  1366.     MOVE.L    4(A6),A0
  1367.             _SysEnvirons
  1368.     MOVE.L    A0,4(A6)
  1369.     EXT.L    D0
  1370.     MOVE.L    D0,(A6)
  1371.     EXG        D4,A7
  1372.     BRA.S    @this.exit
  1373.  
  1374. @noSysEnv
  1375.     fake.SysEnv
  1376.  
  1377. @this.exit
  1378.     RTS
  1379. END-CODE
  1380.  
  1381. GLOBAL
  1382. CODE (CALL).SysEnvirons
  1383.     ( SysEnvRec version -- SysEnvRec result )
  1384.     SysEnvirons.Exist?
  1385.     TST.L    (A6)+
  1386.     BEQ.S    @noSysEnv
  1387.  
  1388.     MOVE.W    2(A6),D0
  1389.     MOVE.L    4(A6),A0
  1390.             _SysEnvirons
  1391.     MOVE.L    A0,4(A6)
  1392.     EXT.L    D0
  1393.     MOVE.L    D0,(A6)
  1394.     BRA.S    @this.exit
  1395.  
  1396. @noSysEnv
  1397.     fake.SysEnv
  1398. @this.exit
  1399.     RTS
  1400. END-CODE MACH
  1401.  
  1402. _SYSENV_ forget.MODULE
  1403.  
  1404. pop.VOCAB.state
  1405.  
  1406. ONLY DEVELOPMENT DEFINITIONS
  1407. ALSO MAC
  1408. ALSO FORTH
  1409. ALSO ASSEMBLER
  1410.  
  1411. ( The following two words are used to restart a suspended task
  1412.   when its Apple Event handler gets called.  Since by definition, 
  1413.   an Apple Event handler gets called while in the IOTASK and using
  1414.   the TRAP-STACK, it is necesary to do a context switch back into
  1415.   the suspended task.  The handler must not PAUSE, since it really is
  1416.   executing inside the environment provided by AEHandleEvent.  This
  1417.   allows the handler access to all of its task variables, and
  1418.   task variables of other tasks.  The handler must leave the OSErr
  1419.   result on the stack and nothing else.  To perform further processing, 
  1420.   leave data in UserVector and UserData. 
  1421.  
  1422.   Use these two words as follows:
  1423.     : my.AE.handler
  1424.         AEHandler.entry
  1425.         (my.AE.handler)   ( the.Apple.Event reply -- OSErr )
  1426.         AEHandler.exit
  1427.         ;
  1428. )
  1429.  
  1430. CODE AEHandler.entry
  1431.     \ stack frame:
  1432.     \   (A7):  return address
  1433.     \  4(A7):  refcon, must be the pointer to task space
  1434.     \  8(A7):  reply
  1435.     \ 12(A7):  AppleEvent
  1436.     \ 16(A7):  OSErr
  1437.     \
  1438.     LINK    A0,#0                    \ setup a stack frame
  1439.     MOVEM.L    D0-D7/A1-A4/A6,-(A7)    \ save all registers
  1440.     MOVE.L    8(A0),A4                \ setup the Task pointer
  1441.     MOVE.L    A7,D4                    \ setup the TrapStack pointer
  1442.     MOVE.L    8(A4),A6                \ get the Task A6 stack
  1443.     MOVEM.L    (A6)+,D5-D7/A2-A3/A7    \ we are now back in the task
  1444.     MOVE.L    A0,-(A6)                \ store addr of stack frame
  1445.     MOVE.L    16(A0),-(A6)            \ theAppleEvent
  1446.     MOVE.L    12(A6),-(A6)            \ reply
  1447.     RTS
  1448. END-CODE MACH
  1449.  
  1450. CODE AEHandler.exit
  1451.     \ the first thing is to re-suspend the task
  1452.     MOVE.L    (A6)+,D0                \ get the OSErr
  1453.     MOVE.L    (A6)+,A0                \ restore the stack frame
  1454.     MOVE.W    D0,20(A0)                \ store the OSErr result
  1455.  
  1456.     MOVEM.L    D5-D7/A2-A3/A7,-(A6)    \ save the task state
  1457.     MOVE.L    A6,$8(A4)                \ save off the A6 stack
  1458.     MOVE.L    D4,A7                    \ restore the callers stack
  1459.     MOVEM.L    (A7)+,D0-D7/A1-A4/A6    \ restore all registers
  1460.     UNLK    A0                        \ unlink the stack frame
  1461.     RTD        #12                        \ and return to the system
  1462.     RTS                                \ need this for the MACH copier
  1463. END-CODE MACH
  1464.  
  1465. CODE AE:
  1466.     JSR        CREATE            \ create the handler
  1467.     JSR        RECURSIVE        \ hide the handler name
  1468.     SUBQ.L    #4,$-1EC(A5)    \ recover code space used by CREATE
  1469.  
  1470.     COMPILE AEHandler.entry    \ compile the glue code
  1471.  
  1472.     MOVE.L    D5,(A3)+        \ push MACH2 internal constant
  1473.     MOVE.L    D6,D5            \ onto return stack
  1474.     MOVE.L    #$99887766,D6
  1475.     JMP        ]                \ start normal compilation
  1476. END-CODE IMMEDIATE 
  1477.  
  1478. CODE ;AE
  1479.     COMPILE AEHandler.exit
  1480.     JMP        ;                \ finish up this definition
  1481. END-CODE IMMEDIATE
  1482.  
  1483. : XDEF:                    ( - branch marker )
  1484.     CREATE  -4 ALLOT
  1485.     $4EFA W,        ( JMP )
  1486.     0 W,            ( entry point to be filled later )
  1487.     0 ,                ( length of routine to be filled later )
  1488.     HERE 6 - 76543    ( marker )
  1489.     ;
  1490.  
  1491. : ;XDEF        {  branch  marker  entry | - }
  1492.  
  1493.     marker 76543 <>  ABORT" XDEF Mismatch!"
  1494.     entry branch - branch W!
  1495.     HERE branch - 2+ branch 2+ !
  1496.     ;
  1497.  
  1498. CODE INIT.prelude
  1499.     MOVE.L    A3,-(A7)
  1500.     LINK    A6,#-2048        \ allocate a 2K FORTH stack
  1501.     [ HERE 2- ]                \ save addr of stack size value
  1502.     MOVE.L    A7,A3            \ setup local loop return stack
  1503.     MOVEM.L    A0-A1,-(A7)        \ save these registers
  1504.     MOVE.L    A0,-(A6)        \ pass pointer to INIT
  1505.     RTS
  1506.     END-CODE MACH
  1507.  
  1508. HERE 2- -    ( get positive offset from end of routine to stack size )
  1509.  
  1510. : Set.INIT.stack=
  1511.     32 WORD NUMBER? 
  1512.     IF
  1513.         NEGATE HERE LITERAL + W!
  1514.     ELSE
  1515.         CR ." A stack size must follow Set.INIT.stack= …" ABORT
  1516.     THEN
  1517.     ; IMMEDIATE
  1518.  
  1519. CODE INIT.epilog
  1520.     MOVEM.L    (A7)+,A0-A1        \ restore stuff
  1521.     UNLK    A6
  1522.     MOVE.L    (A7)+,A3
  1523.     RTS
  1524.     END-CODE MACH
  1525.  
  1526. CODE DA.prelude
  1527.     LINK    A6,#-2048        \ allocate a 2K FORTH stack
  1528.     [ HERE 2- ]                \ push addr of size of parameter stack
  1529.     MOVEM.L    A0-A1,-(A7)        \ save these registers
  1530.     MOVE.L    A6,A3            \ setup local loop return stack
  1531.     SUBA.W    #1792,A3        \ leave space for FP stack
  1532.     [ HERE 2- ]                \ push addr of offset to return stack
  1533.     MOVE.L    A3,D7            \ setup pointer to FP stack
  1534.     MOVE.L    A0,-(A6)        \ pass parameter block
  1535.     MOVE.L    A1,-(A6)        \ pass DCE
  1536.     RTS
  1537.     END-CODE MACH
  1538.  
  1539. HERE 2- -
  1540. SWAP HERE 2- -
  1541.  
  1542. : Set.DA.stack=
  1543.     32 WORD NUMBER? 
  1544.     IF
  1545.         DUP NEGATE HERE LITERAL + W!
  1546.         200 - HERE LITERAL + W!
  1547.     ELSE
  1548.         CR ." A stack size value must follow the word Set.DA.stack= …" ABORT
  1549.     THEN 
  1550.     ; IMMEDIATE
  1551.  
  1552. CODE DA.epilog
  1553.     MOVE.L    (A6)+,D0        \ pass return code
  1554.     MOVEM.L    (A7)+,A0-A1        \ restore stuff
  1555.     UNLK    A6
  1556.     RTS
  1557.     END-CODE MACH
  1558.  
  1559. _FSEQU_ forget.MODULE
  1560. _SYSEQU_ forget.MODULE
  1561.  
  1562. CR .( Use NEW-SEGMENT to write out the new Segment 18 code image )
  1563. CR .( and the new dictionary to a file.)